//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <ddk.h>
#include "usbmass.h"
#include <nu_api.h>
#include <zenr_api.h>

#define MASS_INIT                   0x0000C001
#define MASS_STOP                   0x0000C002
#define MASS_WAKE                   0x0000C003
#define MASS_STOP_BLKCLS            0x0000C004
#define MASS_WAKE_BLKOPN            0x0000C005
#define MASS_CHECK_CONNECT_STATUS   0x0000C008
#define SYNC_CHECK_CONNECT_STATUS   0x0000C018

CUsbMass *g_pUsbMass = NULL;
extern "C" void UsbCallback(int usbEvent, void *ctx)
{
    UInt32 status;
    // USB_CABLE_CONNECT_EVENT 0
    if (0 == usbEvent) {
        status = 0x10;
//        nu_puts("Connect\n");
        nu_notifyDeviceCaller((Int32)&(g_pUsbMass->m_event), status);
    } else if (1 == usbEvent) {
        status = 0x11;
//        nu_puts("DisConnect\n");
        nu_notifyDeviceCaller((Int32)&(g_pUsbMass->m_event), status);
    }

    return;
}

ECode CUsbMass::Control(
        /* [in] */ Handle32 controlCode,
        /* [in] */ const MemoryBuf &inBuffer,
        /* [out] */ MemoryBuf* pOutBuffer,
        /* [out] */ IEvent** ppCompletionEvent)
{
    WaitResult wr;
    EventState status;

    switch (controlCode) {
        case MASS_CHECK_CONNECT_STATUS: {
            EmIsrParameter Param;
            while (TRUE) {
            m_event.Wait(&wr, &status);
                if (status == 0x10) {
                    //kprintf("status %d, %s, %d\n", status, __FILE__, __LINE__);
                    EmPostEventByIsr(215, &Param);
                    //nu_usbMassEnable(1);
                    m_bConnect = TRUE;
                } else if (status == 0x11) {
                    //kprintf("status %d, %s, %d\n", status, __FILE__, __LINE__);
                    EmPostEventByIsr(216, &Param);
                    //nu_usbMassEnable(0);
                    m_bConnect = FALSE;
                }
            }
        }
            break;

        case MASS_INIT:
            break;
        case MASS_STOP: {
                nu_usbMassEnable(0);
        }
            break;
        case MASS_WAKE: {
            nu_usbMassEnable(1);
        }
        break;
        case MASS_STOP_BLKCLS:
        case MASS_WAKE_BLKOPN:
            nu_usbMassEnable(1);
            break;
        default:
            break;
    }
    return NOERROR;
}

ECode UsbMassThreadRoutine(void *arg)
{
    if (g_pUsbMass) {
        g_pUsbMass->Control(MASS_CHECK_CONNECT_STATUS, NULL_MEMORYBUF, NULL, NULL);
    }
    return NOERROR;
}

EXTERN IDeviceDriver * CDECL CreateUsbMass(uint_t uDeviceNo, void *pvParameter)
{
    g_pUsbMass = new CUsbMass;
    if (!g_pUsbMass) {
        DRV_EXPRESSION(ERRORLEVEL, kprintf("not enough memory\n"));
        return NULL;
    }

    nu_initUsbMass(&UsbCallback);

//    if (!nu_Get_UsbSyncReady()) {
        ECode ec;
        ec = DzCreateKernelThread(UsbMassThreadRoutine,
            (PVoid)NULL, CreateThreadFlag_System, ThreadPriorityRank_Normal, NULL);
        if (FAILED(ec)) {
            kprintf("unable to create ctrl thread ec : %08x\n", ec);
            return NULL;
        }
//    }

    kprintf("Init Usb Mass Succeed!\n");
    return g_pUsbMass;
}

